<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>PF: Logging</title>
<link rev="made" href="mailto:www@openbsd.org">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="resource-type" content="document">
<meta name="description"   content="the OpenBSD FAQ page">
<meta name="keywords"      content="openbsd,faq,pf">
<meta name="distribution"  content="global">
</head>

<!--
Copyright (c) 2003, Nick Holland <nick@openbsd.org>
Copyright (c) 2003-2007, Joel Knight <enabled@myrealbox.com>

Permission to use, copy, modify, and distribute this documentation for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.

THE DOCUMENTATION IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS DOCUMENTATION INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS DOCUMENTATION
-->

<body bgcolor="#ffffff" text="#000000">
<!-- Passes validator.w3.org, please keep it this way;
please, use a max of 72 chars per line -->

<a href="../../index.html">
<img alt="[OpenBSD]" height=30 width=141 src="../../images/smalltitle.gif" border="0">
</a>
<p>
[<a href="tagging.html">Previous: Packet Tagging</a>]
[<a href="index.html">Contents</a>]
[<a href="perf.html">Next: Performance</a>]

<p>
<h1><font color="#e00000">PF: Logging</font></h1>

<hr>

<h3>Table of Contents</h3>
<ul>
<li><a href="#intro">Introduction</a>
<li><a href="#log">Logging Packets</a>
<li><a href="#logfile">Reading a Log File</a>
<li><a href="#filter">Filtering Log Output</a>
<li><a href="#syslog">Packet Logging Through Syslog</a>
</ul>

<hr>

<a name="intro"></a>
<h2>Introduction</h2>
When a packet is logged by PF, a copy of the packet header is sent to a
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pflog&amp;sektion=4&amp;manpath=OpenBSD+4.3"
>pflog(4)</a> interface along with some additional data such as the
interface the packet was transiting, the action that PF took (pass or
block), etc.
The pflog(4) interface allows user-space applications to receive PF's
logging data from the kernel.
If PF is enabled when the system is booted, the
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pflogd&amp;sektion=8&amp;manpath=OpenBSD+4.3"
>pflogd(8)</a> daemon is started.
By default pflogd(8) listens on the <tt>pflog0</tt> interface and writes
all logged data to the <tt>/var/log/pflog</tt> file.

<a name="log"></a>
<h2>Logging Packets</h2>
<p>
In order to log packets passing through PF, the <tt>log</tt> keyword
must be used within <a href="nat.html">NAT/rdr</a> and
<a href="filter.html">filter</a> rules.
Note that PF can only log packets that it's blocking or passing; you
cannot specify a rule that only logs packets.

<p>
The <tt>log</tt> keyword causes all packets that match the rule to be
logged.
In the case where the rule is <a href="filter.html#state">creating
state</a>, only the first packet seen (the one that causes the state to
be created) will be logged.

<p>
The options that can be given to the <tt>log</tt> keyword are:

<dl>
<dt><tt>all</tt>
<dd>Causes all matching packets, not just the initial packet, to be
logged.
Useful for rules that create state.

<dt><tt>to <i>pflogN</i></tt>
<dd>Causes all matching packets to be logged to the specified pflog(4)
interface.
For example, when using
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=spamlogd&amp;sektion=8"
>spamlogd(8)</a> all SMTP traffic can be logged to a dedicated pflog(4)
interface by PF.
The spamlogd(8) daemon can then be told to listen on that interface.
This keeps the main PF logfile clean of SMTP traffic which otherwise
would not need to be logged.
Use
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ifconfig&amp;sektion=8"
>ifconfig(8)</a> to create pflog(4) interfaces.
The default log interface <tt>pflog0</tt> is created automatically.

<dt><tt>user</tt>
<dd>Causes the UNIX user-id and group-id that owns the socket that the
packet is sourced from/destined to (whichever socket is local) to be
logged along with the standard log information.
</dl>

<p>
Options are given in parenthesis after the <tt>log</tt> keyword;
multiple options can be separated by a comma or space.

<blockquote>
<tt>
pass in log (all, to pflog1) on $ext_if inet proto tcp to $ext_if port 22 keep state
</tt>
</blockquote>


<a name="logfile"></a>
<h2>Reading a Log File</h2>
The log file written by pflogd is in binary format and cannot be read
using a text editor. Tcpdump must be used to view the log.

<p>
To view the log file:
<blockquote>
<tt>
# tcpdump -n -e -ttt -r /var/log/pflog
</tt>
</blockquote>

<p>
Note that using tcpdump(8) to watch the pflog file does <i>not</i> give
a real-time display. A real-time display of logged packets is achieved
by using the <tt>pflog0</tt> interface:
<blockquote>
<tt>
# tcpdump -n -e -ttt -i pflog0
</tt>
</blockquote>

<p>
<font color="#e00000">NOTE: </font>
When examining the logs, special care should be taken with 
tcpdump's verbose protocol decoding (activated via the 
<tt>-v</tt> command line option). Tcpdump's protocol decoders do not
have a perfect security history.  At least in theory, a delayed attack
could be possible via the partial packet payloads recorded by the
logging device. It is recommended practice to move the log files off of
the firewall machine before examining them in this way.

<p>
Additional care should also be taken to secure access to the logs. By default, 
pflogd will record 96 bytes of the packet in the log file.  Access
to the logs could provide partial access to sensitive packet payloads
(like
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=telnet&amp;sektion=1"
>telnet(1)</a> or
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ftp&amp;sektion=1"
>ftp(1)</a> usernames and passwords).

<a name="filter"></a>
<h2>Filtering Log Output</h2>
Because pflogd logs in tcpdump binary format, the full range of tcpdump
features can be used when reviewing the logs. For example, to only see
packets that match a certain port:
<blockquote>
<tt>
# tcpdump -n -e -ttt -r /var/log/pflog port 80
</tt>
</blockquote>

<p>
This can be further refined by limiting the display of packets to a 
certain host and port combination:
<blockquote>
<tt>
# tcpdump -n -e -ttt -r /var/log/pflog port 80 and host 192.168.1.3
</tt>
</blockquote>

<p>
The same idea can be applied when reading from the <tt>pflog0</tt>
interface:
<blockquote>
<tt>
# tcpdump -n -e -ttt -i pflog0 host 192.168.4.2
</tt>
</blockquote>

<p>
Note that this has no impact on which packets are logged to the pflogd
log file; the above commands only display packets as they are being
logged.

<p>
In addition to using the standard 
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=tcpdump&amp;sektion=8"
>tcpdump(8)</a> filter rules, the tcpdump filter language has been
extended for reading pflogd output:
<ul>
<li><tt>ip</tt> - address family is IPv4.
<li><tt>ip6</tt> - address family is IPv6.
<li><tt>on <i>int</i></tt> - packet passed through the interface
<i>int</i>.
<li><tt>ifname <i>int</i></tt> - same as <tt>on <i>int</i></tt>.
<li><tt>ruleset <i>name</i></tt> - the 
<a href="anchors.html">ruleset/anchor</a> that the packet was matched
in.
<li><tt>rulenum <i>num</i></tt> - the filter rule that the packet matched
was rule number <i>num</i>.
<li><tt>action <i>act</i></tt> - the action taken on the packet.
Possible actions are <tt>pass</tt> and <tt>block</tt>.
<li><tt>reason <i>res</i></tt> - the reason that <tt>action</tt> was 
taken. Possible reasons are <tt>match</tt>, <tt>bad-offset</tt>,
<tt>fragment</tt>, <tt>short</tt>, <tt>normalize</tt>,
<tt>memory</tt>, <tt>bad-timestamp</tt>,
<tt>congestion</tt>, <tt>ip-option</tt>, <tt>proto-cksum</tt>,
<tt>state-mismatch</tt>, <tt>state-insert</tt>, <tt>state-limit</tt>,
<tt>src-limit</tt>, and <tt>synproxy</tt>.
<li><tt>inbound</tt> - packet was inbound.
<li><tt>outbound</tt> - packet was outbound.
</ul>

<p>
Example:
<blockquote>
<tt>
# tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0
</tt>
</blockquote>

<p>
This display the log, in real-time, of inbound packets that were blocked
on the wi0 interface.

<a name="syslog"></a>
<h2>Packet Logging Through Syslog</h2>
In many situations it is desirable to have the firewall logs available
in ASCII format and/or to send them to a remote logging server.  All
this can be accomplished with a small shell script, some minor
changes of the OpenBSD configuration files, and 
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=syslogd&amp;sektion=8"
>syslogd(8)</a>, the logging daemon. Syslogd logs in ASCII and
is also able to log to a remote logging server.

<p>
Create the following script:

<p>
<tt>/etc/pflogrotate</tt>
<pre>
	#!/bin/sh
	PFLOG=/var/log/pflog
	FILE=/var/log/pflog5min.$(date "+%Y%m%d%H%M")
	kill -ALRM $(cat /var/run/pflogd.pid)
	if [ -r $PFLOG ] && [ $(stat -f %z $PFLOG) -gt 24 ]; then
	   mv $PFLOG $FILE
	   kill -HUP $(cat /var/run/pflogd.pid)
	   tcpdump -n -e -ttt -r $FILE | logger -t pf -p local0.info
	   rm $FILE
	fi
</pre>

<p>
Edit root's cron job:
<blockquote>
<tt>
# crontab -u root -e
</tt>
</blockquote>

<p>
Add the following two lines:
<blockquote>
<tt>
# rotate pf log file every 5 minutes<br>
0-59/5 *       *       *       *       /bin/sh /etc/pflogrotate
</tt>
</blockquote>

<p>
Add the following line to <tt>/etc/syslog.conf</tt>:
<blockquote>
<tt>
local0.info &nbsp;&nbsp;&nbsp;&nbsp;/var/log/pflog.txt
</tt>
</blockquote>

<p>
If you also want to log to a remote log server, add the line:
<blockquote>
<tt>
local0.info &nbsp;&nbsp;&nbsp;&nbsp;@syslogger
</tt>
</blockquote>

<p>
Make sure host <i>syslogger</i> has been defined in the
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=hosts&amp;sektion=5"
>hosts(5)</a> file.

<p>
Create the file <tt>/var/log/pflog.txt</tt> to allow syslog to log to
that file, and give it the same permissions as the pflog file.
<blockquote>
<tt>
# touch /var/log/pflog.txt<br>
# chmod 600 /var/log/pflog.txt
</tt>
</blockquote>

<p>
Make syslogd notice the changes by restarting it:
<blockquote>
<tt>
# kill -HUP $(cat /var/run/syslog.pid)
</tt>
</blockquote>

<p>
All logged packets are now sent to <tt>/var/log/pflog.txt</tt>.
If the second line is added they are sent to the remote logging host
<i>syslogger</i> as well.

<p>
The script <tt>/etc/pflogrotate</tt> now processes and then deletes
<tt>/var/log/pflog</tt> so rotation of <tt>pflog</tt> by
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=newsyslog&amp;sektion=8"
>newsyslog(8)</a> is no longer necessary and should be
disabled. However, <tt>/var/log/pflog.txt</tt> replaces
<tt>/var/log/pflog</tt> and rotation of it should be activated.
Change <tt>/etc/newsyslog.conf</tt> as follows:
<pre>
    #/var/log/pflog       600    3    250    *    ZB /var/run/pflogd.pid
    /var/log/pflog.txt    600    7    *      24
</pre>

<p>
PF will now log in ASCII to <tt>/var/log/pflog.txt</tt>. If so 
configured in <tt>/etc/syslog.conf</tt>, it will also log to a remote
server.  The logging is not immediate but it can take up to about 5-6
minutes (the cron job interval) before the logged packets appear in the
file.

<p>
[<a href="tagging.html">Previous: Packet Tagging</a>]
[<a href="index.html">Contents</a>]
[<a href="perf.html">Next: Performance</a>]

<p>
<hr>
<a href="index.html"><img height="24" width="24" src="../../images/back.gif" border="0" alt="[back]"></a> 
<a href="mailto:www@openbsd.org">www@openbsd.org</a>
<br>
<small>$OpenBSD: logging.html,v 1.35 2008/07/27 17:13:47 nick Exp $</small>

</body>
</html> 
